-- Lua Battle System - 优化的决策树系统
-- 提供高性能、可缓存的决策树实现

local Logger = require("utils.logger")
local TableUtils = require("utils.table_utils")

-- 优化的决策树节点基类
local OptimizedDecisionTreeNode = {
    id = "",
    name = "",
    type = "", -- condition, action, leaf
    priority = 0,
    cache_key = "",
    is_cached = false,
    cache_timeout = 0,
    last_cache_update = 0
}

-- 优化的决策树节点构造函数
function OptimizedDecisionTreeNode:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    o.children = {}
    o.cache = {}
    return o
end

-- 条件节点类
local OptimizedConditionNode = OptimizedDecisionTreeNode:new()
OptimizedConditionNode.type = "condition"
OptimizedConditionNode.condition = nil
OptimizedConditionNode.true_child = nil
OptimizedConditionNode.false_child = nil
OptimizedConditionNode.condition_cache = {}

-- 条件节点构造函数
function OptimizedConditionNode:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    o.condition_cache = {}
    return o
end

-- 执行优化的条件判断（带缓存）
function OptimizedConditionNode:evaluate(character, battle_state)
    -- 生成缓存键
    local cache_key = self:generate_cache_key(character, battle_state)

    -- 检查缓存
    if self.condition_cache[cache_key] then
        local cached_result = self.condition_cache[cache_key]
        if os.time() - cached_result.timestamp < 5 then -- 5秒缓存
            return cached_result.value
        else
            self.condition_cache[cache_key] = nil
        end
    end

    -- 执行条件判断
    local result
    if not self.condition then
        Logger.error("条件节点缺少条件判断函数")
        result = false
    else
        result = self.condition(character, battle_state)
    end

    -- 缓存结果
    self.condition_cache[cache_key] = {
        value = result,
        timestamp = os.time()
    }

    return result
end

-- 生成缓存键
function OptimizedConditionNode:generate_cache_key(character, battle_state)
    local key_parts = {
        character.id,
        character.hp,
        character.mp,
        #self:get_alive_allies(battle_state, character.team_id),
        #self:get_alive_enemies(battle_state, character.team_id)
    }
    return table.concat(key_parts, "_")
end

-- 获取存活队友数量
function OptimizedConditionNode:get_alive_allies(battle_state, team_id)
    local allies = {}
    for _, char in ipairs(battle_state.characters) do
        if char.team_id == team_id and char.is_alive then
            table.insert(allies, char)
        end
    end
    return allies
end

-- 获取存活敌人数量
function OptimizedConditionNode:get_alive_enemies(battle_state, team_id)
    local enemies = {}
    for _, char in ipairs(battle_state.characters) do
        if char.team_id ~= team_id and char.is_alive then
            table.insert(enemies, char)
        end
    end
    return enemies
end

-- 动作节点类
local OptimizedActionNode = OptimizedDecisionTreeNode:new()
OptimizedActionNode.type = "action"
OptimizedActionNode.action = nil
OptimizedActionNode.action_cache = {}

-- 动作节点构造函数
function OptimizedActionNode:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    o.action_cache = {}
    return o
end

-- 执行优化的动作
function OptimizedActionNode:execute(character, battle_state)
    if not self.action then
        Logger.error("动作节点缺少动作执行函数")
        return nil
    end

    -- 动作通常不需要缓存，因为每次执行都应该产生不同的结果
    local result = self.action(character, battle_state)
    return result
end

-- 叶子节点类
local OptimizedLeafNode = OptimizedDecisionTreeNode:new()
OptimizedLeafNode.type = "leaf"
OptimizedLeafNode.decision = nil

-- 叶子节点构造函数
function OptimizedLeafNode:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end

-- 优化的决策树类
local OptimizedDecisionTree = {
    id = "",
    name = "",
    root = nil,
    version = "2.0",

    -- 性能优化配置
    optimization_config = {
        enable_caching = true,
        cache_timeout = 10, -- 缓存超时时间（秒）
        max_cache_size = 1000, -- 最大缓存条目数
        enable_precompute = true, -- 启用预计算
        max_depth = 10, -- 最大深度限制
        node_execution_limit = 100 -- 节点执行次数限制
    },

    -- 性能统计
    performance_stats = {
        total_evaluations = 0,
        cache_hits = 0,
        cache_misses = 0,
        average_evaluation_time = 0,
        max_evaluation_time = 0,
        min_evaluation_time = math.huge
    },

    -- 缓存系统
    evaluation_cache = {},
    node_cache = {}
}

-- 优化的决策树构造函数
function OptimizedDecisionTree:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    o:init()
    return o
end

-- 初始化决策树
function OptimizedDecisionTree:init()
    self.evaluation_cache = {}
    self.node_cache = {}
    self.performance_stats = {
        total_evaluations = 0,
        cache_hits = 0,
        cache_misses = 0,
        average_evaluation_time = 0,
        max_evaluation_time = 0,
        min_evaluation_time = math.huge
    }
end

-- 设置根节点
function OptimizedDecisionTree:set_root(node)
    self.root = node
    Logger.info("优化决策树根节点已设置: " .. node.name)
end

-- 优化的决策树评估
function OptimizedDecisionTree:evaluate(character, battle_state)
    -- 性能监控开始
    local start_time = os.clock()

    if not self.root then
        Logger.error("决策树没有根节点")
        return nil
    end

    -- 生成全局缓存键
    local global_cache_key = self:generate_global_cache_key(character, battle_state)

    -- 检查全局缓存
    if self.optimization_config.enable_caching then
        local cached_result = self:get_cached_result(global_cache_key)
        if cached_result then
            self:record_performance_stats(start_time, true)
            return cached_result
        end
    end

    -- 执行决策树评估
    local result = self:evaluate_node_optimized(self.root, character, battle_state, 0)

    -- 缓存结果
    if self.optimization_config.enable_caching and result then
        self:cache_result(global_cache_key, result)
    end

    -- 记录性能统计
    self:record_performance_stats(start_time, false)

    return result
end

-- 优化的节点评估
function OptimizedDecisionTree:evaluate_node_optimized(node, character, battle_state, depth)
    -- 深度限制检查
    if depth >= self.optimization_config.max_depth then
        Logger.warn("决策树达到最大深度限制: " .. self.optimization_config.max_depth)
        return nil
    end

    -- 执行次数限制检查
    self.performance_stats.total_evaluations = self.performance_stats.total_evaluations + 1
    if self.performance_stats.total_evaluations > self.optimization_config.node_execution_limit then
        Logger.warn("决策树执行次数超限")
        return nil
    end

    if node.type == "condition" then
        -- 条件节点 - 使用优化的评估
        local result = node:evaluate(character, battle_state)

        if result then
            -- 条件为真，执行真分支
            if node.true_child then
                return self:evaluate_node_optimized(node.true_child, character, battle_state, depth + 1)
            end
        else
            -- 条件为假，执行假分支
            if node.false_child then
                return self:evaluate_node_optimized(node.false_child, character, battle_state, depth + 1)
            end
        end
    elseif node.type == "action" then
        -- 动作节点
        return node:execute(character, battle_state)
    elseif node.type == "leaf" then
        -- 叶子节点，返回决策
        return node.decision
    end

    return nil
end

-- 生成全局缓存键
function OptimizedDecisionTree:generate_global_cache_key(character, battle_state)
    local key_parts = {
        self.id,
        character.id,
        math.floor(character.hp),
        math.floor(character.mp),
        character.team_id,
        self:count_alive_characters(battle_state),
        self:get_battle_phase(battle_state)
    }
    return table.concat(key_parts, "|")
end

-- 计算存活角色数量
function OptimizedDecisionTree:count_alive_characters(battle_state)
    local count = 0
    for _, char in ipairs(battle_state.characters) do
        if char.is_alive then
            count = count + 1
        end
    end
    return count
end

-- 获取战斗阶段
function OptimizedDecisionTree:get_battle_phase(battle_state)
    local total_chars = #battle_state.characters
    local alive_chars = self:count_alive_characters(battle_state)

    if alive_chars == total_chars then
        return "early"
    elseif alive_chars > total_chars * 0.5 then
        return "mid"
    else
        return "late"
    end
end

-- 获取缓存结果
function OptimizedDecisionTree:get_cached_result(cache_key)
    local cached_entry = self.evaluation_cache[cache_key]
    if cached_entry then
        -- 检查缓存是否过期
        if os.time() - cached_entry.timestamp < self.optimization_config.cache_timeout then
            self.performance_stats.cache_hits = self.performance_stats.cache_hits + 1
            return cached_entry.result
        else
            -- 删除过期缓存
            self.evaluation_cache[cache_key] = nil
        end
    end

    self.performance_stats.cache_misses = self.performance_stats.cache_misses + 1
    return nil
end

-- 缓存结果
function OptimizedDecisionTree:cache_result(cache_key, result)
    -- 检查缓存大小限制
    if TableUtils.get_table_size(self.evaluation_cache) >= self.optimization_config.max_cache_size then
        self:cleanup_old_cache()
    end

    self.evaluation_cache[cache_key] = {
        result = result,
        timestamp = os.time()
    }
end

-- 清理旧缓存
function OptimizedDecisionTree:cleanup_old_cache()
    local current_time = os.time()
    local keys_to_remove = {}

    for key, entry in pairs(self.evaluation_cache) do
        if current_time - entry.timestamp > self.optimization_config.cache_timeout then
            table.insert(keys_to_remove, key)
        end
    end

    for _, key in ipairs(keys_to_remove) do
        self.evaluation_cache[key] = nil
    end

    -- 如果还是太多，删除最旧的条目
    if TableUtils.get_table_size(self.evaluation_cache) >= self.optimization_config.max_cache_size then
        local oldest_key = nil
        local oldest_time = current_time

        for key, entry in pairs(self.evaluation_cache) do
            if entry.timestamp < oldest_time then
                oldest_time = entry.timestamp
                oldest_key = key
            end
        end

        if oldest_key then
            self.evaluation_cache[oldest_key] = nil
        end
    end
end

-- 记录性能统计
function OptimizedDecisionTree:record_performance_stats(start_time, cache_hit)
    local end_time = os.clock()
    local evaluation_time = (end_time - start_time) * 1000 -- 转换为毫秒

    -- 更新最大和最小时间
    self.performance_stats.max_evaluation_time = math.max(self.performance_stats.max_evaluation_time, evaluation_time)
    self.performance_stats.min_evaluation_time = math.min(self.performance_stats.min_evaluation_time, evaluation_time)

    -- 更新平均时间
    local total_time = self.performance_stats.average_evaluation_time * (self.performance_stats.total_evaluations - 1) + evaluation_time
    self.performance_stats.average_evaluation_time = total_time / self.performance_stats.total_evaluations
end

-- 获取性能报告
function OptimizedDecisionTree:get_performance_report()
    local stats = self.performance_stats
    local cache_hit_rate = 0

    if stats.cache_hits + stats.cache_misses > 0 then
        cache_hit_rate = stats.cache_hits / (stats.cache_hits + stats.cache_misses) * 100
    end

    return {
        total_evaluations = stats.total_evaluations,
        average_evaluation_time = stats.average_evaluation_time,
        max_evaluation_time = stats.max_evaluation_time,
        min_evaluation_time = stats.min_evaluation_time,
        cache_hit_rate = cache_hit_rate,
        cache_size = TableUtils.get_table_size(self.evaluation_cache)
    }
end

-- 构建优化的攻击决策树
function OptimizedDecisionTree:build_optimized_attack_tree()
    -- 根节点：是否有可用攻击技能
    local root = OptimizedConditionNode:new({
        id = "root",
        name = "是否有可用攻击技能",
        condition = function(character, battle_state)
            for _, skill in ipairs(character.skills) do
                if skill:is_usable(character) and skill.damage and skill.damage.base > 0 then
                    return true
                end
            end
            return false
        end
    })

    -- 快速路径：检查是否有必杀机会
    local has_finisher_chance = OptimizedConditionNode:new({
        id = "has_finisher_chance",
        name = "是否有必杀机会",
        condition = function(character, battle_state)
            for _, enemy in ipairs(battle_state.characters) do
                if enemy.team_id ~= character.team_id and enemy.is_alive then
                    local health_percentage = enemy.hp / enemy.max_hp
                    if health_percentage < 0.2 then
                        -- 检查是否有足够的伤害完成击杀
                        for _, skill in ipairs(character.skills) do
                            if skill:is_usable(character) and skill.damage and skill.damage.base >= enemy.hp then
                                return true
                            end
                        end
                    end
                end
            end
            return false
        end
    })

    -- 必杀动作
    local execute_finisher = OptimizedLeafNode:new({
        id = "execute_finisher",
        name = "执行必杀",
        decision = {
            type = "skill",
            priority = 100,
            strategy = "execute_finisher"
        }
    })

    -- 高价值目标检查
    local has_high_value_target = OptimizedConditionNode:new({
        id = "has_high_value_target",
        name = "是否有高价值目标",
        condition = function(character, battle_state)
            for _, enemy in ipairs(battle_state.characters) do
                if enemy.team_id ~= character.team_id and enemy.is_alive then
                    -- 优先攻击治疗者和法师
                    if enemy.magic_attack > enemy.attack or enemy.hp < enemy.max_hp * 0.7 then
                        return true
                    end
                end
            end
            return false
        end
    })

    -- 攻击高价值目标
    local attack_high_value = OptimizedLeafNode:new({
        id = "attack_high_value",
        name = "攻击高价值目标",
        decision = {
            type = "skill",
            priority = 90,
            strategy = "attack_high_value_target"
        }
    })

    -- AOE技能检查
    local has_aoe_opportunity = OptimizedConditionNode:new({
        id = "has_aoe_opportunity",
        name = "是否有AOE机会",
        condition = function(character, battle_state)
            -- 检查是否有多个敌人聚集
            local enemy_count = 0
            for _, enemy in ipairs(battle_state.characters) do
                if enemy.team_id ~= character.team_id and enemy.is_alive then
                    enemy_count = enemy_count + 1
                end
            end
            return enemy_count >= 2
        end
    })

    -- 使用AOE技能
    local use_aoe_skill = OptimizedLeafNode:new({
        id = "use_aoe_skill",
        name = "使用AOE技能",
        decision = {
            type = "skill",
            priority = 85,
            strategy = "use_aoe_skill"
        }
    })

    -- 普通攻击
    local normal_attack = OptimizedLeafNode:new({
        id = "normal_attack",
        name = "普通攻击",
        decision = {
            type = "skill",
            priority = 70,
            strategy = "normal_attack"
        }
    })

    -- 没有攻击技能时的后备选项
    local use_item = OptimizedConditionNode:new({
        id = "use_item_backup",
        name = "是否使用物品",
        condition = function(character, battle_state)
            for item_id, quantity in pairs(character.items) do
                if quantity > 0 then
                    return true
                end
            end
            return false
        end
    })

    local use_item_action = OptimizedLeafNode:new({
        id = "use_item_action",
        name = "使用物品",
        decision = {
            type = "item",
            priority = 50,
            strategy = "use_best_item"
        }
    })

    local defend = OptimizedLeafNode:new({
        id = "defend_backup",
        name = "防御",
        decision = {
            type = "defend",
            priority = 30
        }
    })

    -- 构建优化的树结构
    root.true_child = has_finisher_chance
    root.false_child = use_item

    has_finisher_chance.true_child = execute_finisher
    has_finisher_chance.false_child = has_high_value_target

    has_high_value_target.true_child = attack_high_value
    has_high_value_target.false_child = has_aoe_opportunity

    has_aoe_opportunity.true_child = use_aoe_skill
    has_aoe_opportunity.false_child = normal_attack

    use_item.true_child = use_item_action
    use_item.false_child = defend

    self.root = root
    Logger.info("优化攻击决策树构建完成")
end

-- 构建优化的防御决策树
function OptimizedDecisionTree:build_optimized_defense_tree()
    -- 根节点：自身是否需要紧急治疗
    local root = OptimizedConditionNode:new({
        id = "root",
        name = "是否需要紧急治疗",
        condition = function(character, battle_state)
            local health_percentage = character.hp / character.max_hp
            return health_percentage < 0.25
        end
    })

    -- 紧急治疗检查
    local has_emergency_heal = OptimizedConditionNode:new({
        id = "has_emergency_heal",
        name = "是否有紧急治疗手段",
        condition = function(character, battle_state)
            -- 检查治疗技能
            for _, skill in ipairs(character.skills) do
                if skill:is_usable(character) and skill.healing and skill.healing.base > 0 then
                    return true
                end
            end
            -- 检查治疗物品
            for item_id, quantity in pairs(character.items) do
                if quantity > 0 and item_id:find("potion") then
                    return true
                end
            end
            return false
        end
    })

    -- 执行紧急治疗
    local emergency_heal = OptimizedLeafNode:new({
        id = "emergency_heal",
        name = "紧急治疗",
        decision = {
            type = "mixed",
            priority = 100,
            strategy = "emergency_heal"
        }
    })

    -- 检查队友需要治疗
    local needs_ally_heal = OptimizedConditionNode:new({
        id = "needs_ally_heal",
        name = "队友是否需要治疗",
        condition = function(character, battle_state)
            for _, ally in ipairs(battle_state.characters) do
                if ally.team_id == character.team_id and ally.is_alive and ally.id ~= character.id then
                    local health_percentage = ally.hp / ally.max_hp
                    if health_percentage < 0.3 then
                        return true
                    end
                end
            end
            return false
        end
    })

    -- 治疗队友
    local heal_ally = OptimizedLeafNode:new({
        id = "heal_ally",
        name = "治疗队友",
        decision = {
            type = "skill",
            priority = 90,
            strategy = "heal_critical_ally"
        }
    })

    -- 检查是否需要增益
    local needs_buff = OptimizedConditionNode:new({
        id = "needs_buff",
        name = "是否需要增益效果",
        condition = function(character, battle_state)
            -- 检查是否有增益技能
            for _, skill in ipairs(character.skills) do
                if skill:is_usable(character) and skill.type == "support" then
                    return true
                end
            end
            return false
        end
    })

    -- 使用增益技能
    local apply_buff = OptimizedLeafNode:new({
        id = "apply_buff",
        name = "使用增益技能",
        decision = {
            type = "skill",
            priority = 80,
            strategy = "apply_best_buff"
        }
    })

    -- 防御姿态
    local defend_stance = OptimizedLeafNode:new({
        id = "defend_stance",
        name = "防御姿态",
        decision = {
            type = "defend",
            priority = 70
        }
    })

    -- 检查反击机会
    local has_counter_chance = OptimizedConditionNode:new({
        id = "has_counter_chance",
        name = "是否有反击机会",
        condition = function(character, battle_state)
            -- 检查是否有低生命值的敌人
            for _, enemy in ipairs(battle_state.characters) do
                if enemy.team_id ~= character.team_id and enemy.is_alive then
                    local health_percentage = enemy.hp / enemy.max_hp
                    if health_percentage < 0.4 then
                        return true
                    end
                end
            end
            return false
        end
    })

    -- 反击攻击
    local counter_attack = OptimizedLeafNode:new({
        id = "counter_attack",
        name = "反击攻击",
        decision = {
            type = "skill",
            priority = 75,
            strategy = "counter_attack"
        }
    })

    -- 构建树结构
    root.true_child = has_emergency_heal
    root.false_child = needs_ally_heal

    has_emergency_heal.true_child = emergency_heal
    has_emergency_heal.false_child = defend_stance

    needs_ally_heal.true_child = heal_ally
    needs_ally_heal.false_child = has_counter_chance

    has_counter_chance.true_child = counter_attack
    has_counter_chance.false_child = needs_buff

    needs_buff.true_child = apply_buff
    needs_buff.false_child = defend_stance

    self.root = root
    Logger.info("优化防御决策树构建完成")
end

-- 清理缓存系统
function OptimizedDecisionTree:clear_cache()
    self.evaluation_cache = {}
    Logger.info("决策树缓存已清理")
end

-- 获取优化建议
function OptimizedDecisionTree:get_optimization_suggestions()
    local report = self:get_performance_report()
    local suggestions = {}

    if report.cache_hit_rate < 50 then
        table.insert(suggestions, "缓存命中率较低，考虑增加缓存超时时间")
    end

    if report.average_evaluation_time > 10 then
        table.insert(suggestions, "平均评估时间较长，考虑简化决策树逻辑")
    end

    if report.cache_size > self.optimization_config.max_cache_size * 0.8 then
        table.insert(suggestions, "缓存接近上限，考虑增加缓存清理频率")
    end

    return suggestions
end

-- 导出模块
local OptimizedDecisionTreeModule = {
    OptimizedDecisionTreeNode = OptimizedDecisionTreeNode,
    OptimizedConditionNode = OptimizedConditionNode,
    OptimizedActionNode = OptimizedActionNode,
    OptimizedLeafNode = OptimizedLeafNode,
    OptimizedDecisionTree = OptimizedDecisionTree
}

return OptimizedDecisionTreeModule